home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000 #2
/
Ham Radio 2000 - Volume 2.iso
/
HAMV2
/
MISC
/
DTMFF110
/
DTMF.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-08-05
|
7KB
|
274 lines
/* DTMF.C */
/* Author: Emil LAURENTIU */
/* Last modified: Tuesday, 05 August 1997 */
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <string.h>
#include "freq.h"
extern char matrix_dtmf[4][4];
extern int f_dtmf[];
extern double f_ctcss[];
extern int sb_f_dtmf[];
extern int dtmf_delay;
extern int sb_addr;
static unsigned ticking = 0;
static FM_Instrument instrument = {
0x3f, 0x3f, /* Level */
0x00, 0x00, /* Multiple */
0x00, 0x00, /* Attack */
0x00, 0x00, /* Decay */
0x0f, 0x0f, /* Sustain */
0x00, 0x00, /* Release */
0x00, 0x00, /* WaveSelect */
0x00, 0x00, /* Amp_Vib_EnvG */
0x01, 0x00 /* Algorithm, Feedback */
};
int notes[12] = {0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5,
0x202, 0x220, 0x241, 0x263, 0x287, 0x2AE};
/* dtmf.c 05/08/97 23.37.34 */
unsigned char op_p( int voice, int op );
void Sb_FM_Reset( void );
void Sb_FM_Key_Off( int voice );
void Sb_FM_Key_On( int voice, int freq, int octave );
void Sb_FM_Voice_Volume( int voice, int op, int vol );
void Sb_FM_Voice_At_De( int voice, int op, int atack, int decay );
void Sb_FM_Voice_Su_Re( int voice, int op, int sustain, int release );
void Sb_FM_Voice_Character( int voice, int op, int amp_vib_envg, int multiple );
void Sb_FM_Voice_WaveSelect( int voice, int op, int wave );
void Sb_FM_Voice_FeedBack( int voice, int type, int strength );
void Sb_FM_Set_Voice( int voice, FM_Instrument * ins );
void interrupt new_timer( void );
unsigned long timer_hiticks( void );
void delay_loop( int time );
void generate_DTMF( char *nr );
double generate_CTCSS( int gen_ctcss );
static void
WriteFM( int addr, unsigned char data )
{
int i;
/* Left Channel */
outportb( sb_addr + 0, addr );
for ( i = 0; i < 6; i++ )
inportb( sb_addr + 0 );
outportb( sb_addr + 1, data );
for ( i = 0; i < 35; i++ )
inportb( sb_addr + 0 );
/* Rigth Channel */
outportb( sb_addr + 2, addr );
for ( i = 0; i < 6; i++ )
inportb( sb_addr + 2 );
outportb( sb_addr + 3, data );
for ( i = 0; i < 35; i++ )
inportb( sb_addr + 2 );
}
unsigned char
op_p( int voice, int op )
{
unsigned char c;
c = ( --voice ) % 9;
c = ( c / 3 ) << 3 | c % 3;
c += 3 * ( ( --op ) & 1 );
return ( c );
}
void
Sb_FM_Reset( void )
{
int i;
WriteFM( 1, 0x20 ); /* FM waveform */
WriteFM( 4, 0 ); /* disable timers */
WriteFM( 8, 0 ); /* select FM music mode */
WriteFM( 0xbd, 0xc0 ); /* no drums */
for ( i = 1; i <= 9; i++ )
{
Sb_FM_Key_Off( i );
Sb_FM_Voice_WaveSelect( i, 1, 0 );
Sb_FM_Voice_WaveSelect( i, 2, 0 );
}
}
void
Sb_FM_Key_Off( int voice )
{
WriteFM( 0xB0 + ( --voice ) % 9, 0 ); /* turn voice off */
}
void
Sb_FM_Key_On( int voice, int freq, int octave )
{
--voice;
voice %= 9;
WriteFM( 0xb0 + voice, 0 );
WriteFM( 0xa0 + voice, freq & 0xff );
WriteFM( 0xb0 + voice, ( freq >> 8 ) | ( octave << 2 ) | 0x20 );
}
void
Sb_FM_Voice_Volume( int voice, int op, int vol )
{
WriteFM( 0x40 + op_p( voice, op ), ~vol & 0x3f | 0x40 );
}
void
Sb_FM_Voice_At_De( int voice, int op, int atack, int decay )
{
WriteFM( 0x60 + op_p( voice, op ), ( ~atack & 0xf ) << 4 | decay & 0xf );
}
void
Sb_FM_Voice_Su_Re( int voice, int op, int sustain, int release )
{
WriteFM( 0x80 + op_p( voice, op ), ( sustain & 0xf ) << 4 | ~release & 0xf );
}
void
Sb_FM_Voice_Character( int voice, int op, int amp_vib_envg, int multiple )
{
WriteFM( 0x20 + op_p( voice, op ), ( amp_vib_envg & 7 ) << 5 | ( multiple + 1 ) & 0xf );
}
void
Sb_FM_Voice_WaveSelect( int voice, int op, int wave )
{
WriteFM( 0xe0 + op_p( voice, op ), wave & 3 );
}
void
Sb_FM_Voice_FeedBack( int voice, int type, int strength )
{
WriteFM( 0xc0 + ( --voice ) % 9, ( strength & 7 ) << 1 | type & 1 );
}
void
Sb_FM_Set_Voice( int voice, FM_Instrument * ins )
{
int op;
for ( op = 1; op <= 2; op++ )
{
Sb_FM_Voice_Volume( voice, op, ins->Level[op - 1] );
Sb_FM_Voice_At_De( voice, op, ins->Atack[op - 1], ins->Decay[op - 1] );
Sb_FM_Voice_Su_Re( voice, op, ins->Sustain[op - 1], ins->Release[op - 1] );
Sb_FM_Voice_Character( voice, op, ins->Amp_Vib_EnvG[op - 1], ins->Multiple[op - 1] );
Sb_FM_Voice_WaveSelect( voice, op, ins->WaveSelect[op - 1] );
}
Sb_FM_Voice_FeedBack( voice, ins->Algorithm, ins->Feedback );
}
void interrupt
new_timer( )
{
ticking++;
outportb( 0x20, 0x20 ); /* Send EOI */
}
unsigned long
timer_hiticks( )
{
outportb( 0x43, 0x00 ); /* Send latch command to 8253 counter 0 */
return ( ( unsigned long ) ticking << 16 ) |
( unsigned ) -( inportb( 0x40 ) | ( inportb( 0x40 ) << 8 ) );
}
void
delay_loop( int time ) /* Delay is in milisecond increments */
{
unsigned long val;
val = timer_hiticks( ) + 1193L * time;
while ( val > timer_hiticks( ) ); /* Wait */
}
void
generate_DTMF( char *nr )
{
int i, j;
int xoff = WINDOW_LEFT;
char nc;
int key;
void interrupt( *old_int ) ( );
disable( );
old_int = getvect( 8 ); /* timer */
setvect( 8, new_timer );
enable( );
Sb_FM_Set_Voice( 1, &instrument );
Sb_FM_Set_Voice( 2, &instrument );
Sb_FM_Voice_Volume( 1, 1, 0x3f );
Sb_FM_Voice_Volume( 2, 1, 0x3f );
Sb_FM_Voice_Volume( 1, 2, 0x3f );
Sb_FM_Voice_Volume( 2, 2, 0x3f );
while ( *nr )
{
key = 0;
for ( i = 0; i < 4; i++ )
for ( j = 0; j < 4; j++ )
if ( matrix_dtmf[i][j] == *nr )
{
key++;
Sb_FM_Key_On( 1, sb_f_dtmf[i], 5 );
Sb_FM_Key_On( 2, sb_f_dtmf[j + 4], 6 );
}
nc = *( nr + 1 );
*( nr + 1 ) = 0;
draw_text_left( xoff, MGY, nr );
xoff += 8;
*( nr + 1 ) = nc;
if ( key )
delay_loop( dtmf_delay << 1 );
Sb_FM_Key_Off( 1 );
Sb_FM_Key_Off( 2 );
if ( !key )
delay_loop( dtmf_delay << 1 );
delay_loop( dtmf_delay );
nr++;
}
Sb_FM_Voice_Volume( 1, 1, 0 );
Sb_FM_Voice_Volume( 2, 1, 0 );
Sb_FM_Voice_Volume( 1, 2, 0 );
Sb_FM_Voice_Volume( 2, 2, 0 );
disable( );
setvect( 8, old_int );
enable( );
}
double
generate_CTCSS( int gen_ctcss )
{
double err = 0;
const double step = 1e5 / 2097152;
int factor, multiply;
if ( gen_ctcss == CTCSS_MAX )
Sb_FM_Key_Off( 3 );
else
{
Sb_FM_Set_Voice( 3, &instrument );
multiply = f_ctcss[gen_ctcss] / step / 1024;
multiply++;
WriteFM( 0x20 + op_p( 3, 1 ), multiply ); /* use freq * multiply */
WriteFM( 0x20 + op_p( 3, 2 ), multiply ); /* for better resolution */
factor = f_ctcss[gen_ctcss] / step / multiply + 0.5;
err = step * factor * multiply - f_ctcss[gen_ctcss];
Sb_FM_Key_On( 3, factor, 0 ); /* use ocatave 0 */
WriteFM( 0x40 + op_p( 3, 1 ), 0xC0 ); /* maximum volume (0x3F) */
WriteFM( 0x40 + op_p( 3, 2 ), 0xC0 ); /* 6 db/octave decrease */
}
return ( err );
}